/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package engine.linkList;

/**
 *
 * @author hjp
 */
import engine.decoder.ID3Decoder;

import java.io.*;

/**
 * 链表管理模块
 * 管理播放器中所有链表
 */
public class LinkedListManager implements Serializable {
    private static final long serialVersionUID = -4362540391043925941L;

    /**
     * 当前GUI显示的歌单集合
     */
    transient MusicLists currentVisitMusicLists;//不需要被序列化存储，播放器启动之后直接置为“创建的歌单”createMusicLists。即显示创建的歌单

    /**
     * 当前GUI显示的歌单
     */
    transient Node<MusicListNode> currentVisitMusicList;//不需要被序列化存储,播放器启动之后直接置为创建的歌单中的第一个歌单

    /**
     * 播放器本次启动时已下载完成的音乐的链表
     */
    transient Node<MusicListNode> downloadedListNode;//不需要被序列化。每次播放器启动时候都直接生成新的包含0个结点的链表

    /**
     * 当前正在下载的乐曲的列表
     */
    transient Node<MusicListNode> downlaodingListNode;//不需要被序列化。每次播放器启动时候都直接生成新的包含0个结点的链表

    /**
     * 爬虫返回的歌单集合
     * P.S.有好多歌单，但总数是确定的。这一部分是爬虫返回的歌单。
     */
    transient MusicLists[] crawlerMusicLists;//不需要被序列化。每次播放器启动时候都调用爬虫模块以初始化

    /**
     * 本地歌单
     */
    transient Node<MusicListNode> localListNode;//不需要被序列化。播放器启动的时候，执行扫描以初始化

    /**
     * 创建的歌单集合
     */
    MusicLists createMusicLists;//需要被序列化

    /**
     * 收藏的歌单集合
     */
    MusicLists collectedMusicLists;//需要被序列化

    /**
     * 待扫描的本地文件夹的链表
     */
    LocalToScanFolderList localToScanFolderList;//需要被序列化


    /**
     * 单例模式
     */
    static LinkedListManager manager = new LinkedListManager();

    /**
     * 单例模式
     */
    public static LinkedListManager getInstance(){
        return manager;
    }

    public Node<MusicListNode> getLocalListNode(){
        return localListNode;
    }

    public MusicLists getCreateMusicLists() {
        return createMusicLists;
    }

    public MusicLists getCollectedMusicLists() {
        return collectedMusicLists;
    }

    public LocalToScanFolderList getLocalToScanFolderList(){
        return localToScanFolderList;
    }
    
    public Node<MusicListNode> getCurrentVisitMusicList(){
        return currentVisitMusicList;
    }
    
    public MusicLists getCurrentVisitMusicLists(){
        return currentVisitMusicLists;
    }

    private LinkedListManager(){
    }

    /**
     * 设定当前GUI显示的MusicLists
     */
    public void setCurrentVisitMusicLists(MusicLists currentVisitMusicLists) {
        this.currentVisitMusicLists = currentVisitMusicLists;
    }

    /**
     * 设定当前GUI显示的MusicList
     */
    public void setCurrentVisitMusicList(Node<MusicListNode> currentVisitMusicList) {
        this.currentVisitMusicList = currentVisitMusicList;
    }
    
    public void setLocalListNode(Node<MusicListNode> localListNode){
        this.localListNode = localListNode;
    }

    /**
     * 扫描 LocalToScanFolderList ，并且得到本地音乐播放链表
     */
    public Node<MusicListNode> scanAndCreateLocalListNode(){
        MusicListNode localList = new MusicListNode();
        Node<LocalToScanFolderNode> p = localToScanFolderList.head;
        String folderPath;
        while(p != null){
            folderPath = p.info.path;
            //当且仅当该文件夹被选中才执行扫描
            if (p.info.isSelect) {
                scanAndCreateLocalListNode(localList,folderPath);
            }
            p = p.next;
        }
        localList.isModify = false;
        return new Node<>(localList);
    }

    private void scanAndCreateLocalListNode(MusicListNode localList,String folderPath){
        File directory = new File(folderPath);
        File[] fileList = directory.listFiles();
        //给出的文件路径指向一个目录，且目录非空
        if (directory.isDirectory() && fileList != null){
            for (File file : fileList){
                //如果不是目录，且是MP3文件的话，执行解码
                String fileName = file.getAbsolutePath();
                if (!file.isDirectory() &&
                        (fileName.substring(fileName.lastIndexOf(".") + 1)).equalsIgnoreCase("mp3")){
                    ID3Decoder.decode(file.getAbsolutePath());
                    MusicNode newNode = new MusicNode(ID3Decoder.getSongName(),ID3Decoder.getArtist(),
                            ID3Decoder.getAlbum(),ID3Decoder.getTime(),ID3Decoder.getSize());
                    newNode.setFilePath(file.getAbsolutePath());
                    //添加到链表中
                    localList.addTail(new Node<>(newNode));
                    //localList.isModify = false;
                }
                else if (file.isDirectory()){
                    //是目录，则递归处理
                    scanAndCreateLocalListNode(localList,file.getAbsolutePath());
                }
            }
        }
    }

    /**
     * 添加一个待扫描的文件夹
     */
    public void addLocalToScanFolderNode(String path){
        LocalToScanFolderNode newNode = new LocalToScanFolderNode(path);
        localToScanFolderList.addTail(new Node<>(newNode));
    }


    /**
     * 将当前GUI所显示的歌单按照指定的分类方式分类
     */
    public MusicLists classify(ClassifyBy groupBy){
        if (currentVisitMusicList != null) {
            return currentVisitMusicList.info.classify(groupBy);
        }
        return null;
    }

//    /**
//     * 将指定的歌单按照指定的分类方式执行分类
//     */
//    public MusicLists classify(MusicListNode musicListNode,ClassifyBy groupBy){
//        return musicListNode.classify(groupBy);
//    }

    /**
     * 在当前GUI所显示的歌单中执行搜索
     */
    public Node<MusicListNode> searchInMusicList(String key){
        if (currentVisitMusicList != null) {
            return currentVisitMusicList.info.search(key);
        }
        return null;
        //如果对搜索结构歌单中的歌曲执行下一首播放，应当等价视为插播，
        // 即不修改当前GUI显示的歌单currentVisitMusicList
    }

    /**
     *在歌单的集合中执行搜索。
     */
    public MusicLists searchInMusicLists(String key){
        if (currentVisitMusicLists != null) {
            return currentVisitMusicLists.search(key);
        }
        return null;
        //todo 1.在歌单的集合中搜索符合条件的歌单的时候，应当修改
        // currentVisitMusicLists字段
        // 这是因为，GUI显示的内容大多数时候取决于currentVisitMusicList，
        // 只在对本地音乐执行分类的时候，GUI才需要currentVisitMusicLists以显示内容
        //todo 2.GUI部分需要重绘 给GUI发出重绘指令？
    }

//    /**
//     *对指定的歌单执行搜索
//     */
//    public Node<MusicListNode> search(MusicListNode musicListNode,String key){
//        return musicListNode.search(key);
//    }



    /**
     * 对当前GUI显示的歌单执行按照指定关键字的排序
     */
    public Node<MusicListNode> sort(SortBy sortBy){
        if (currentVisitMusicList != null) {
            return currentVisitMusicList.info.sort(sortBy);
        }
        return null;
    }

    /**
     * 创建一个新的歌单
     */
    public void createNewMusicList(String listName){
        MusicListNode musicListNode = new MusicListNode(listName);
        createMusicLists.addTail(new Node<>(musicListNode));
    }

    /**
     * 将指定的音乐收藏到指定的歌单里面
     * @param index 字段 collectedMusicLists 中所管理的第index个歌单
     */
    public void collectMusic(Node<MusicNode> newMusicNode,int index){
        Node<MusicListNode> p = createMusicLists.head;
        --index;
        while (index != 0){
            p = p.next;
            --index;
        }
        Node<MusicNode> newNode = new Node<>(newMusicNode.info);
        p.info.addHead(newNode);
    }

    /**
     *收藏某个歌单
     */
    public void collectMusicList(Node<MusicListNode> newMusicListNode){
        Node<MusicListNode> newList = new Node<>(newMusicListNode.info);
        collectedMusicLists.addTail(newList);
        //todo GUI部分需要重绘 给GUI发出重绘指令？
    }

    /**
     * 从当前GUI显示的歌单中删除某首歌曲
     */
    public void deleteMusic(int index){
        currentVisitMusicList.info.delete(index);
        //当所有歌曲都被删除时，将删除该歌单
        if (currentVisitMusicList.info.sum == 0){
            int x = 1;
            Node<MusicListNode> p = currentVisitMusicLists.head;
            while (p != currentVisitMusicList){
                p = p.next;
                ++x;
            }
            deleteMusicList(currentVisitMusicLists,x);
        }
        //todo GUI部分需要重绘 给GUI发出重绘指令？
    }

    /**
     * 删除指定MusicLists中的第index个歌单
     */
    public void deleteMusicList(MusicLists selectedMusicLists,int index){
        //删除第index个歌单的时候，检查是否为当前正在播放的歌单，
        // 如果是，则将播放调度器的currentPlayMusicLists和currentPlayMusicList都置空
        Node<MusicListNode> p = selectedMusicLists.head;
        int x = index;
        x--;
        while (x != 0){
            p = p.next;
            x--;
        }
        if (p == PlayScheduleManager.manager.currentPlayMusicList){
            PlayScheduleManager.manager.currentPlayMusicList = null;
            PlayScheduleManager.manager.currentPlayMusicLists = null;
        }
        selectedMusicLists.delete(index);
    }
    
    /**
     * 从给定的歌单集合中找到给定名字的歌单结点
     */
    public Node<MusicListNode> findSetectedMusicList(MusicLists selectedMusicLists,String musicListName){
        Node<MusicListNode> p = selectedMusicLists.head;
        while(p != null){
            if (musicListName.equals(p.info.listName)) {
                return p;
            }
            p = p.next;
        }
        return null;
    }
    
    public  Node<LocalToScanFolderNode> findSelectedLocalToScanFolderNode(String folderPath){
        Node<LocalToScanFolderNode> p = localToScanFolderList.head;
        while(p != null){
            if (folderPath.equals(p.info.path)) {
                return p;
            }
            p = p.next;
        }
        return null;
    }
}

